# @FileName  :  auth.py
# @Time      :  2025/8/26 15:20
# @Author    :  Ayanami
# @info      :
from datetime import timedelta
from typing import Union

from fastapi import APIRouter, Depends, HTTPException, status, Request
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from app.schemas.auth import (
    UserRegister, UserLogin, Token, TokenRefresh,UserType,
    UserInfo, PasswordChange, PasswordReset, PasswordResetConfirm
)
from app.crud.auth import user_crud
from app.core.security import create_access_token, create_refresh_token, verify_token
from app.core.config import settings
from app.schemas.teacher import TeacherCreate
from app.schemas.student import StudentCreate
from app.schemas.agent import AgentCreate

router = APIRouter(tags=["认证"])
security = HTTPBearer()


async def get_current_user(credentials: HTTPAuthorizationCredentials = Depends(security)):
    """获取当前用户"""
    token = credentials.credentials
    payload = verify_token(token)
    user_id = payload.get("sub")
    if user_id is None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Could not validate credentials"
        )

    user = await user_crud.get_user_by_username(user_id)
    if user is None:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="User not found"
        )

    return user


@router.post("/create-profile", response_model=dict)
async def create_profile(
        teacher_data: TeacherCreate = None,
        student_data: StudentCreate = None,
        agent_data: AgentCreate = None,
        current_user=Depends(get_current_user)
):
    """创建用户个人资料"""
    # 检查是否已经有个人资料
    if (current_user.user_type == UserType.TEACHER and current_user.teacher_id) or \
            (current_user.user_type == UserType.STUDENT and current_user.student_id) or \
            (current_user.user_type == UserType.ADMIN and current_user.agent_id):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Profile already exists"
        )

    # 根据用户类型选择正确的数据
    if current_user.user_type == UserType.TEACHER:
        if not teacher_data:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Teacher profile data is required for teacher user type"
            )
        profile_dict = teacher_data.model_dump()
    elif current_user.user_type == UserType.STUDENT:
        if not student_data:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Student profile data is required for student user type"
            )
        profile_dict = student_data.model_dump()
    elif current_user.user_type == UserType.ADMIN:
        if not agent_data:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Agent profile data is required for admin user type"
            )
        profile_dict = agent_data.model_dump()
    else:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Invalid user type"
        )

    # 创建个人资料并关联
    result = await user_crud.create_user_profile(current_user.id, profile_dict)

    if not result:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Failed to create profile"
        )

    return {"message": "Profile created successfully", "data": result}

@router.post("/register", response_model=dict)
async def register(user_data: UserRegister, request: Request):
    """用户注册"""
    try:
        user = await user_crud.create_user(user_data)

        # 记录注册日志
        client_ip = request.client.host
        user_agent = request.headers.get("user-agent", "")
        await user_crud.log_login_attempt(
            user_id=user.id,
            login_ip=client_ip,
            user_agent=user_agent,
            is_success=True
        )

        return {
            "message": "User registered successfully",
            "user_id": user.id,
            "username": user.username
        }
    except HTTPException:
        raise
    except Exception as e:
        # 更详细地记录错误信息
        print(f"Registration error: {str(e)}")
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"Registration failed: {str(e)}"
        )


@router.post("/login", response_model=Token)
async def login(user_data: UserLogin, request: Request):
    """用户登录"""
    client_ip = request.client.host
    user_agent = request.headers.get("user-agent", "")

    # 验证用户
    user = await user_crud.authenticate_user(user_data.username, user_data.password)

    if not user:
        # 记录失败日志
        await user_crud.log_login_attempt(
            user_id=None,
            login_ip=client_ip,
            user_agent=user_agent,
            is_success=False,
            failure_reason="Invalid credentials"
        )
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Incorrect username or password"
        )

    # 更新最后登录时间
    await user_crud.update_last_login(user)

    # 记录成功日志
    await user_crud.log_login_attempt(
        user_id=user.id,
        login_ip=client_ip,
        user_agent=user_agent,
        is_success=True
    )

    # 生成令牌
    access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
    refresh_token_expires = timedelta(days=settings.REFRESH_TOKEN_EXPIRE_DAYS)

    access_token = create_access_token(
        data={"sub": user.username, "user_id": user.id, "user_type": user.user_type},
        expires_delta=access_token_expires
    )
    refresh_token = create_refresh_token(
        data={"sub": user.username, "user_id": user.id},
        expires_delta=refresh_token_expires
    )

    # 获取用户详细信息
    user_info = await user_crud.get_user_with_details(user.id)

    return Token(
        access_token=access_token,
        refresh_token=refresh_token,
        expires_in=settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60,
        user_info=user_info
    )


@router.post("/refresh", response_model=Token)
async def refresh_token(token_data: TokenRefresh):
    """刷新令牌"""
    try:
        payload = verify_token(token_data.refresh_token)
        username = payload.get("sub")
        user_id = payload.get("user_id")

        if username is None or user_id is None:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="Invalid refresh token"
            )

        user = await user_crud.get_user_by_username(username)
        if user is None or user.id != user_id:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail="User not found"
            )

        # 生成新的访问令牌
        access_token_expires = timedelta(minutes=settings.ACCESS_TOKEN_EXPIRE_MINUTES)
        access_token = create_access_token(
            data={"sub": user.username, "user_id": user.id, "user_type": user.user_type},
            expires_delta=access_token_expires
        )

        user_info = await user_crud.get_user_with_details(user.id)

        return Token(
            access_token=access_token,
            refresh_token=token_data.refresh_token,  # 刷新令牌保持不变
            expires_in=settings.ACCESS_TOKEN_EXPIRE_MINUTES * 60,
            user_info=user_info
        )

    except HTTPException:
        raise
    except Exception:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Invalid refresh token"
        )


@router.get("/me", response_model=dict)
async def get_current_user_info(current_user=Depends(get_current_user)):
    """获取当前用户信息"""
    user_info = await user_crud.get_user_with_details(current_user.id)
    return user_info


@router.post("/change-password")
async def change_password(
        password_data: PasswordChange,
        current_user=Depends(get_current_user)
):
    """修改密码"""
    success = await user_crud.change_password(
        current_user,
        password_data.old_password,
        password_data.new_password
    )

    if not success:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Old password is incorrect"
        )

    return {"message": "Password changed successfully"}


@router.post("/forgot-password")
async def forgot_password(reset_data: PasswordReset):
    """忘记密码"""
    user = await user_crud.get_user_by_email(reset_data.email)
    if not user:
        # 为了安全，即使用户不存在也返回成功消息
        return {"message": "If email exists, reset instructions have been sent"}

    # 生成重置令牌
    token = await user_crud.generate_password_reset_token(user)

    # 这里应该发送邮件，暂时返回令牌（生产环境中不应该返回）
    return {
        "message": "Reset token generated",
        "token": token  # 生产环境中应该通过邮件发送
    }


@router.post("/reset-password")
async def reset_password(reset_data: PasswordResetConfirm):
    """重置密码"""
    success = await user_crud.reset_password_with_token(
        reset_data.token,
        reset_data.new_password
    )

    if not success:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Invalid or expired reset token"
        )

    return {"message": "Password reset successfully"}


@router.post("/logout")
async def logout(current_user=Depends(get_current_user)):
    """用户登出"""
    # 这里可以将令牌加入黑名单，或者更新用户状态
    return {"message": "Logged out successfully"}